using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Web;
using System.Web.Services;
using System.Net;
using System.IO;
using dmWS.enableFramework;


namespace dmWS
{
	/// <summary>
	/// Summary description for enableFramework.
	/// </summary>
	[WebService(Namespace="http://e4.txt.it/dm")]
	public class documentManagement : System.Web.Services.WebService
	{
		public documentManagement()
		{
			//CODEGEN: This call is required by the ASP.NET Web Services Designer
			InitializeComponent();
		}

		#region Component Designer generated code
		
		//Required by the Web Services Designer 
		private IContainer components = null;
				
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if(disposing && components != null)
			{
				components.Dispose();
			}
			base.Dispose(disposing);		
		}
		
		#endregion

		
		
		[WebMethod (Description = "Uploads a document on server. Parameters: "+
			 "username (username of person who is uploading document, who must be already registered on database) ."+
			 "efDocument (object with valorized Name, Description) "+
			 "efUrl (object containing url of new document) "+
			 "Return value: url of web page upload.aspx "+
			 "In case of error, it returns exception string ") ]		
			//efUrl
		public efURL uploadDocument(string ownerName, efDocument documento, efURL url)
		{
			try
			{
			string host = System.Configuration.ConfigurationSettings.AppSettings["uploadUrl"].ToString();
				
				string nome = "";
				if (documento.Name != null)
					nome = documento.Name;

				string descrizione = "";
				if (documento.Description != null)
					descrizione = documento.Description;

				string indi = "";
				if (url.Url != null)
					indi = System.Web.HttpUtility.UrlEncode(url.Url);

				string rifobj = "";
				if (documento.ReferenceObj != null)
					rifobj = documento.ReferenceObj;

				string rifid = "";
				if (documento.ReferenceId != null)
					rifid = documento.ReferenceId;
			
				string page = "upload.aspx?refId="+rifid+"&refObj="+rifobj+"&nameDoc="+nome+"&description="+descrizione+"&owner="+ownerName+"&id=&urlRed="+indi;
				efURL urlRet = new efURL();
				string indirizzo = host+page;
				string ritorno = replaceUrl(indirizzo);
				urlRet.Url = ritorno;
				return urlRet;
				/*
				KTManage kt = new KTManage();
			
				string folderid = System.Configuration.ConfigurationSettings.AppSettings["enabFolder"].ToString();
				string ktfs = System.Configuration.ConfigurationSettings.AppSettings["ktfilesystem"].ToString();
				string ktfsWeb = System.Configuration.ConfigurationSettings.AppSettings["ktfsWeb"].ToString();
				//string user = System.Configuration.ConfigurationSettings.AppSettings["user"].ToString();

				string urlrep = url.Replace('\\', '/');
				string [] pezziurl = url.Split('/');
				string filename = (pezziurl[pezziurl.Length-1]).ToString();  //l'ultima voce dell'array
				string docid_cvid = kt.createKtDocument(url, ownerId, folderid, filename); 
				string[] pezzi = docid_cvid.Split('_');
			
				string size = downloadFile(url, ktfs+"originals\\" );
				kt.updateDocSize(pezzi[1].ToString(), size);
				kt.updateDocFilename(pezzi[1].ToString(), filename);

				//ritorno l'url del documento originale	
				string finalUrl = ktfsWeb + "originals/" + filename;
				string arrayUrl = replaceUrl(finalUrl);
				string[] ritorno = {arrayUrl, pezzi[0]};			
			
				return ritorno;
				*/
			}
			catch (Exception ex)
			{
				efURL urlRet = new efURL();
				urlRet.Error.CodErr = "1";
				urlRet.Error.DesErr = ex.Message;
				return urlRet;
			}
		}

		
		private string replaceUrl(string url)
		{
			string extName = System.Configuration.ConfigurationSettings.AppSettings["serverExtName"].ToString();
			string intName = System.Configuration.ConfigurationSettings.AppSettings["serverIntName"].ToString();
			string ris = url.Replace(intName, extName);
			return ris;
		}


		[WebMethod (Description = "Returns web address of the latest version of the document. Parameters: "+
			 "efDocument (object with valorized Id of document) "+
			 "return value: efURL object with web address of the latest version of the document. "+
			 "In case of error, efURL object has valorized error field with an efError object. ") ]	
		public efURL downloadDocument(efDocument documento, string username)
		{
			try
			{
				string documentId = documento.Id;
				KTManage kt = new KTManage();
				string ktfsWeb = System.Configuration.ConfigurationSettings.AppSettings["ktfsWeb"].ToString();
				string filename = "";
				string query = "select filename from document_content_version where document_id = "+documentId+
					" and id = (select max(id) from document_content_version where document_id = "+documentId+" )";
				DataBase db = kt.Db;
				MySql.Data.MySqlClient.MySqlDataReader rea = db.ExecuteQuery(query);
				while (rea.Read())
				{
					filename = rea["filename"].ToString();
				}

				string finalUrl = ktfsWeb + filename;
		
				//sistemo l'url con quella visibile all'esterno
				string urlReplaced = replaceUrl(finalUrl);

				efURL ris = new efURL();
				ris.Url = urlReplaced;
				return ris;
			}
			catch (Exception ex)
			{
				efURL ris = new efURL();
				efError errore = new efError();
				errore.CodErr = "1";
				errore.DesErr = ex.Message;
				ris.Error = errore;
				return ris;
			}
		}
	
		[WebMethod (Description = "Adds a new version of an existing document. Parameters: "+
			 "url (web url of file, ex. http://host/folder/document.documentManagement ) "+
			 "document (efDocument object, with valorized name, description and id of previous document) "+
			 "ownerName (username of person who is uploading file ). "+
			 "Return value: new document's web address "+
			 "In case of error, the return value is an exception message") ]		
		public efURL addVersion(efDocument documento, string ownerName, efURL url)
		{
			string ris = "";
			try
			{
				KTManage kt = new KTManage();
				string host = System.Configuration.ConfigurationSettings.AppSettings["uploadUrl"].ToString();
				
				string nome = "";
				if (documento.Name != null)
					nome = documento.Name;

				string descrizione = "";
				if (documento.Description != null)
					descrizione = documento.Description;

				string docid = "";
				if (documento.Id != null)
					docid = documento.Id;

				string indi = "";
				if (url.Url != null)
					indi = url.Url;

				string refId = "";
				if (documento.ReferenceId != null)
					refId = documento.ReferenceId;

				string refObj = "";
				if (documento.ReferenceObj != null)
					refObj = documento.ReferenceObj;
				
				string page = "upload.aspx?nameDoc="+nome+"&description="+descrizione+"&owner="+ownerName+"&id="+docid+"&urlRed="+indi+"&refId="+refId+"&refObj="+refObj;
				efURL urlRet = new efURL();
				urlRet.Url = host+page;
				return urlRet;
				//string user = System.Configuration.ConfigurationSettings.AppSettings["user"].ToString();
				/*
				string contentVersionId = kt.addKTVersion(url, ownerId, previousId);

				string urlrep = url.Replace('\\', '/');
				string [] pezziurl = urlrep.Split('/');
				string filename = (pezziurl[pezziurl.Length-1]).ToString();  
				string ktfs = System.Configuration.ConfigurationSettings.AppSettings["ktfilesystem"].ToString();
				string ktfsWeb = System.Configuration.ConfigurationSettings.AppSettings["ktfsWeb"].ToString();  
				string size = downloadFile(url, ktfs+"originals\\" );
				kt.updateDocSize(contentVersionId, size);
				kt.updateDocFilename(contentVersionId, filename);

				//ritorno l'url del documento nel server
				string finalUrl = ktfsWeb + "originals/" + filename;

				//sistemo l'url con quella visibile all'esterno
				ris = replaceUrl(finalUrl);
				*/
			}
			catch (Exception ex)
			{
				efURL urlRet = new efURL();
				urlRet.Error.CodErr = "1";
				urlRet.Error.DesErr = ex.Message;
				return urlRet;
			}
		}
		
		[WebMethod (Description = " It returns a list of all existing versions of a document. Parameters: "+
			 "documentId (document identifier). "+
			 "Return value: an array composed by as many strings as document versions, "+
			 "and every string is the correspondent filename. "+
			 "In case of error, the return value is an array of dimension 1 with the exception message. ") ]	
		//TO DO: URLCollection come valore di ritorno
		public string[] getAllVersions(int documentId, string username)
		{
			try
			{
				
				EfDocumentObj docuObj = EfDocumentObj.getEfDocumentObj(documentId.ToString());
				ArrayList lista = docuObj.versions; //lista di oggetti EfVersionObj, che sono EfDocumentObj
				
				efDocument[] arrayEfDocuments = new efDocument[lista.Count];
				string[] arrayStrings = new string[lista.Count];

				for (int i=0; i<lista.Count; i++)
				{
					//con il casting mantengo solo gli attributi del documento
					//ma io devo trasformare in EfDocument una specifica versione del documento
					//lo faccio fare alla classe di dovere
					efDocument docu = docuObj.getEfDocumentOfVersion(i);
					arrayEfDocuments[i] = docu;

					arrayStrings[i] = System.Configuration.ConfigurationSettings.AppSettings["ktfsWeb"].ToString()+docu.FileName;
				}
				return arrayStrings;
				
				/*
				string query = "select filename from document_content_version "+
					"where document_id="+documentId+" order by id";
				KTManage kt = new KTManage();
				MySql.Data.MySqlClient.MySqlDataReader rea = kt.Db.ExecuteQuery(query);
				ArrayList lista = new ArrayList();
				while (rea.Read())
				{
					lista.Add(rea["filename"].ToString());
				}
				rea.Close();
				string[] ris = new string[lista.Count];
				for (int i=0; i<lista.Count; i++)
				{
					ris[i] = lista[i].ToString();
				}

				return ris;
				*/
			}
			catch (Exception ex)
			{
				string[] risu = new string[1];
				risu[0] = ex.Message;
				return risu;
			}
		}

		[WebMethod (Description = "It gets a specific version of a document. Parameters: "+
			 "documentId (document identifier), "+
			 "versionId (identifier of required version; by default, 1 is the version identifier of every new document) ."+
			 "Return value: web address of required document "+
			 "In case of error, the return value is an exception message") ]	
		public efURL getVersion(int documentId, int versionId, string username)
		{
			try
			{
				string query = "select filename from document_content_version "+
					"where document_id="+documentId+" order by id";
				KTManage kt = new KTManage();
				MySql.Data.MySqlClient.MySqlDataReader rea = kt.Db.ExecuteQuery(query);
				int counter = 1;
				string ris = "";
				while (rea.Read())
				{
					if (versionId == counter)
					{
						ris = System.Configuration.ConfigurationSettings.AppSettings["ktfsWeb"].ToString()+rea["filename"].ToString();
						break;
					}
					counter++;
				}
				rea.Close();

				efURL ret = new efURL();
				ret.Url = replaceUrl(ris);
				return ret;
			}
			catch (Exception ex)
			{
				efURL ret = new efURL();
				ret.Error = getE4error(ex.Message);
				return ret;
			}
			
		}



		[WebMethod (Description = "It sets as deleted document specified, so it is not physically removed. "+
			 "Parameters: identifier of document to delete. "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]		
		public efError deleteDocument(int documentId, string username)
		{
			string ris = "";
			try
			{
				KTManage kt = new KTManage();
				ris = kt.changeStatus(documentId.ToString(), "3");
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}

		private efError getE4error(string mainResult)
		{
			efError errore = new efError();
			errore.DesErr = mainResult;

			if (mainResult == "")
				errore.CodErr = "0";
			else
				errore.CodErr = "1";

			return errore;

			}


		[WebMethod (Description = "It includes back in the repository a document which has been "+
			 "set as deleted with deleteDocument. "+
			 "Parameters: identifier of document to restore. "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]		
		public efError restoreDocument(int documentId, string username)
		{
			string ris = "";
			try
			{
				KTManage kt = new KTManage();
				ris = kt.changeStatus(documentId.ToString(), "1");
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}

		
		[WebMethod (Description = "It makes visible a documents only to his owner. "+
			 "Parameters: identifier of document to reserve. "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]		
		public efError reserveDocument(int documentId, string username)
		{
			string ris = "";
			try
			{
				KTManage kt = new KTManage();
				ris = kt.changeStatus(documentId.ToString(), "6");
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}


		[WebMethod (Description = "It makes a reserved document visible back to everyone. "+
			 "Parameters: identifier of document to unreserve. "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]	
		public efError unreserveDocument(int documentId, string username)
		{
			string ris = "";
			try
			{
				KTManage kt = new KTManage();
				ris = kt.changeStatus(documentId.ToString(), "1");
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}


		[WebMethod (Description = "It gives a list of all documents which has been set as deleted. "+
			 "Parameters: none. "+
			 "Return value: an array composed by as many strings as documents. "+
			 "In case of error, the return value is an array of dimension 1 with the exception message. ") ]				
		//TO DO: mettere UrlCollection
		public string[] getDeleted()
		{
			try
			{
				string folder = System.Configuration.ConfigurationSettings.AppSettings["enabFolder"].ToString();
				string query = "select document_content_version.filename from documents "+
					" join document_content_version on (documents.id = document_content_version.document_id) "+
					" where documents.folder_id="+folder+" and documents.status_id=3 ";
				KTManage kt = new KTManage();
				MySql.Data.MySqlClient.MySqlDataReader rea = kt.Db.ExecuteQuery(query);
				ArrayList lista = new ArrayList();
				while (rea.Read())
				{
					lista.Add(rea["filename"].ToString());
				}
				rea.Close();
				string[] ris = new string[lista.Count];
				for (int i=0; i<lista.Count; i++)
				{
					ris[i] = lista[i].ToString();
				}
				return ris;
			}
			catch(Exception ex)
			{
				string[] risu = new string[1];
				risu[0] = ex.Message;
				return risu;
			}
		}


		private string downloadFileKT(string source, string destfolder, string docid)
		{
			//string sourcefolder = "http://braveheart/invoke/documents/Atles.odt";
			//string destfolder = "C:\\Program Files\\ktdms\\knowledgeTree\\Documents\\";
			
			int barra = source.LastIndexOf('/')+1;
			string sourcefolder = source.Substring(0, barra );
			string filename = source.Substring(barra, source.Length-barra);
			
			WebClient webc = new WebClient();
			string folder = "";
			//webc.DownloadFile(sourcefolder+filename, destfolder+filename);
			int id = Convert.ToInt32(docid);
			if (id<100)
				folder = "00";
			else
			{
				string iniz = docid.Substring(0,1);
				folder = "0"+iniz;
			}
			try
			{
				webc.DownloadFile(sourcefolder+filename, destfolder+"\\"+folder+"\\"+docid);
			}
			catch(Exception ex)
			{
				string str = ex.Message;
			}

			FileInfo scaricato = new FileInfo(destfolder+"\\"+folder+"\\"+docid);
			string size = scaricato.Length.ToString();
			return size; 

		}

		
		[WebMethod (Description = "It physically deletes, permanently, all documents set as deleted. "+
			 "Parameters: none. "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]	
		public efError purgeBasket(string username)
		{
			string ris = svuotaCestino(0);
			return getE4error(ris);
		}

		[WebMethod (Description = "It physically deletes, permanently, all documents set as deleted "+
			 " and belonging to specified user. "+
			 "Parameters: ownerName (username of the owner of documents to expunge) . "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]		
		public efError purgeUserBasket(string ownerName, string username)
		{
			KTManage kt = new KTManage();
			string userId = kt.getUserId(ownerName);
			int idi = Convert.ToInt32(userId);
			string ris = svuotaCestino(idi);
			return getE4error(ris);
		}


		private string svuotaCestino(int ownerId)
		{
			string ris = "";
			try
			{
				KTManage kt = new KTManage();
				string folder = System.Configuration.ConfigurationSettings.AppSettings["enabFolder"].ToString();
				string query = "select document_content_version.storage_path, documents.id from "+
					" document_content_version join documents on ( document_content_version.document_id "+
					" = documents.id) where documents.folder_id="+folder+" and documents.status_id=3 ";
				if (ownerId != 0)
					query += " and documents.creator_id= "+ownerId.ToString();
				MySql.Data.MySqlClient.MySqlDataReader rea = kt.Db.ExecuteQuery(query);
			
				ArrayList sp = new ArrayList(); //storage_path dei documenti da cancellare fisicamente
				ArrayList idi = new ArrayList(); //document_id dei documenti da cancellare nel db
				while (rea.Read())
				{
					sp.Add(rea["storage_path"].ToString());
					idi.Add(rea["id"].ToString());
				}
				rea.Close();
				kt.Db.CloseConnection();

				//elimino i documenti dal db di kt
				for (int j=0; j<idi.Count; j++)
				{
					kt.expungeKTDocument(idi[j].ToString());
				}

				//elimino i documenti fisicamente
				string ktfs = System.Configuration.ConfigurationSettings.AppSettings["ktfilesystem"].ToString();
				for (int i=0; i<sp.Count; i++)
				{
					string fullpath = ktfs + sp[i].ToString();
					FileInfo current = new FileInfo(fullpath);
					current.Delete();
				}

			}
			catch (Exception ex)
			{
				ris = ex.Message;
			}
			return ris;
		}
		

		public void expungeDocument(string documentId)
		{
			KTManage kt = new KTManage();
			string query = "select storage_path from document_content_version where document_id="+documentId;
			MySql.Data.MySqlClient.MySqlDataReader rea = kt.Db.ExecuteQuery(query);
			ArrayList lista = new ArrayList();
			while (rea.Read())
			{
				lista.Add(rea["storage_path"].ToString());
			}
			rea.Close();
			kt.Db.CloseConnection();

			string ktfs = System.Configuration.ConfigurationSettings.AppSettings["ktfilesystem"].ToString();
			for (int i=0; i<lista.Count; i++)
			{
				string fullpath = ktfs + lista[i].ToString();
				FileInfo current = new FileInfo(fullpath);
				current.Delete();
			}

			kt.expungeKTDocument(documentId);
		}


		public string downloadFile(string source, string destfolder)
		{
			//string sourcefolder = "http://braveheart/invoke/documents/Atles.odt";
			//string destfolder = "C:\\Program Files\\ktdms\\knowledgeTree\\Documents\\odf\\";
			
			int barra = source.LastIndexOf('/')+1;
			string sourcefolder = source.Substring(0, barra );
			string filename = source.Substring(barra, source.Length-barra);
			
			WebClient webc = new WebClient();
			try
			{
				webc.DownloadFile(sourcefolder+filename, destfolder+filename);
			}
			catch(Exception ex)
			{
				string str = ex.Message;
			}

			FileInfo scaricato = new FileInfo(destfolder+filename);
			string size = scaricato.Length.ToString();
			return size; 
		}

		[WebMethod (Description = " It inserts a new user into database. "+
             "Parameters: efUser object with fields Id, Login, Name and Surname valorized "+
	         "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]	
		public efError notifyNewUser(efUser utente)
		{
			string ris = "";
			try
			{
				UserManage um = new UserManage();
				if (utente.Id==null || utente.Login==null)
				{
					efError error = getE4error("Id and Login fields must be set");
					return error;
				}

				string nome = utente.Name+" "+utente.Surname;
				nome = nome.Trim();
				if (nome!="")
					ris = um.insertUser(utente.Id, utente.Login, nome);
				else
					ris = um.insertUser(utente.Id, utente.Login, "");
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}

		[WebMethod (Description = " It updates user data into database. "+
			 "Parameters: efUser object with fields Id, Login, Name and Surname valorized "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]	
		public efError notifyUpdateUser(efUser utente)
		{
			string ris = "";
			try
			{
				if (utente.Id==null || utente.Login==null)
				{
					efError error = getE4error("Id and Login fields must be set");
					return error;
				}

				UserManage um = new UserManage();
				string nome = utente.Name + " " + utente.Surname;
				nome = nome.Trim();
				ris = um.changeField(utente.Id, "name", nome);
				ris = um.changeField(utente.Id, "username", utente.Login);
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}

		[WebMethod (Description = " It deletes an user from database. "+
			 "Parameters: efUser object with fields Id valorized "+
			 "Return value: efError object, with CodErr=0 and DesErr = empty string. "+
			 "In case of error, CodErr = code corresponding to verified error, "+
			 "DesErr = exception message")]	
		public efError notifyDeleteUser(efUser utente)
		{
			string ris = "";
			try
			{
				if (utente.Id==null)
				{
					efError error = getE4error("Id field must be set");
					return error;
				}
				UserManage um = new UserManage();
				ris = um.deleteUser(utente.Id);
			}
			catch (Exception ex)
			{ ris = ex.Message; }

			efError errore = getE4error(ris);
			return errore;
		}

	}
}
